﻿#include "Dispatcher.h"
#include <sys/epoll.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include "EpollDispatcher.h"

EpollDispatcher::EpollDispatcher(EventLoop* evloop) : Dispatcher(evloop)
{
	m_epfd = epoll_create(10);//初始化epoll树
	if (m_epfd == -1)
	{
		perror("epoll_create");
		exit(0);
	}
	m_events = new struct epoll_event[m_maxNode];//定义传出参数
	m_name = "Epoll";
}

EpollDispatcher::~EpollDispatcher()
{
	close(m_epfd);
	delete[]m_events;
}

int EpollDispatcher::add()
{
	int ret = epollCtl(EPOLL_CTL_ADD);
	if (ret == -1)
	{
		perror("epoll_crl add");
		exit(0);
	}
	return ret;
}

int EpollDispatcher::remove()
{
	int ret = epollCtl(EPOLL_CTL_DEL);
	if (ret == -1)
	{
		perror("epoll_crl delete");
		exit(0);
	}
	// 通过 channel 释放对应的 TcpConnection 资源
	m_channel->destroyCallback(const_cast<void*>(m_channel->getArg()));

	return ret;
}

int EpollDispatcher::modify()
{
	int ret = epollCtl(EPOLL_CTL_MOD);
	if (ret == -1)
	{
		perror("epoll_crl modify");
		exit(0);
	}
	return ret;
}

int EpollDispatcher::dispatch(int timeout)
{
	int count = epoll_wait(m_epfd, m_events, m_maxNode, timeout * 1000);//阻塞等待就绪事件
	for (int i = 0; i < count; ++i)
	{
		int events = m_events[i].events;
		int fd = m_events[i].data.fd;
		if (events & EPOLLERR || events & EPOLLHUP)//判断就绪事件的类型，并传入任务结点channel响应的回调函数中
		{
			// 对方断开了连接, 删除 fd
			// epollRemove(Channel, evLoop);
			continue;
		}
		if (events & EPOLLIN)
		{
			m_evLoop->eventActive(fd, (int)FDEvent::ReadEvent);
		}
		if (events & EPOLLOUT)
		{
			m_evLoop->eventActive(fd, (int)FDEvent::WriteEvent);
		}
	}
	return 0;
}

int EpollDispatcher::epollCtl(int op)//参数op为epoll_ctl 操作枚举值 ，例如：EPOLL_CTL_ADD
{
	struct epoll_event ev;
	ev.data.fd = m_channel->getSocket();//获取文件描述符
	int events = 0;
	if (m_channel->getEvent() & (int)FDEvent::ReadEvent)//判断要监听的事件
	{
		events |= EPOLLIN;
	}
	if (m_channel->getEvent() & (int)FDEvent::WriteEvent)
	{
		events |= EPOLLOUT;
	}
	ev.events = events;
	int ret = epoll_ctl(m_epfd, op, m_channel->getSocket(), &ev);//对文件描述符进行处理
	return ret;
}